#include "data_queue.h"

#include <memory.h>

const ElementType DATA_QUEUE_DEFAULT_VALUE = 0;

void DATA_QueueInit(DATA_Queue *queue) {
    queue->_last = -1;
}

void DATA_QueueEnqueue(DATA_Queue *queue, const ElementType element) {
    if (queue->_last == DATA_QUEUE_SIZE - 1) {
        for (int i = 1; i < DATA_QUEUE_SIZE; ++i)
            queue->data[i - 1] = queue->data[i];
        queue->data[queue->_last] = element;
        return;
    }

    queue->data[++queue->_last] = element;
}

void DATA_QueueClear(DATA_Queue *queue) {
    queue->_last = -1;
}

ElementType DATA_QueueGet(const DATA_Queue *queue, const int32_t index) {
    const int32_t length = DATA_QueueLength(queue);
    if (length < -index || length <= index) return DATA_QUEUE_DEFAULT_VALUE;

    return index < 0
        ? queue->data[length + index]
        : queue->data[index];
}

ElementType DATA_QueueSum(const DATA_Queue *queue) {
    const int32_t length = DATA_QueueLength(queue);
    ElementType sum = 0;
    for (int32_t i = 0; i < length; i++) {
        sum += queue->data[i];
    }
    return sum;
}

float DATA_QueueAvg(const DATA_Queue *queue) {
    return (float)DATA_QueueSum(queue) / (float)DATA_QueueLength(queue);
}

float DATA_QueueVariance(const DATA_Queue *queue) {
    const int32_t length = DATA_QueueLength(queue);
    const float avg = DATA_QueueAvg(queue);
    float variance = 0;
    for (int32_t i = 0; i < length; ++i) {
        const float current = (float)queue->data[i] - avg;
        variance += current * current;
    }
    variance /= (float)length;
    return variance;
}

int32_t DATA_QueueLength(const DATA_Queue *queue) {
    return queue->_last + 1;
}
